<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>数据类型的检测方法 | 悄悄的卷，然后卷死所有人</title>
    <meta name="description" content="这是一个奇怪的地方">
    <link rel="stylesheet" href="/blobview/assets/style.019f39fc.css">
    <link rel="modulepreload" href="/blobview/assets/Home.d05cdc04.js">
    <link rel="modulepreload" href="/blobview/assets/app.a4363fd4.js">
    <link rel="modulepreload" href="/blobview/assets/fe_secondary_interviews_jstype.md.b3e700ba.lean.js">
    <link rel="modulepreload" href="/blobview/assets/app.a4363fd4.js">
    <meta name="twitter:title" content="数据类型的检测方法 | 悄悄的卷，然后卷死所有人">
    <meta property="og:title" content="数据类型的检测方法 | 悄悄的卷，然后卷死所有人">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme"><header class="nav-bar" data-v-675d8756><div class="sidebar-button" data-v-675d8756><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class></path></svg></div><a class="nav-bar-title" href="/blobview/" aria-label="悄悄的卷，然后卷死所有人, back to home" data-v-675d8756 data-v-4a583abe><!----> 悄悄的卷，然后卷死所有人</a><div class="flex-grow" data-v-675d8756></div><div class="nav" data-v-675d8756><nav class="nav-links" data-v-675d8756 data-v-eab3edfe><!--[--><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/" data-v-b8818f8c>Home <!----></a></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>前端君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>面试八股文</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/algorithm" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>算法大卷</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/errormd/chrome插件开发指南" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>坑你太美</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>稀奇君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>web3</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/b" data-v-b8818f8c>杂谈君 <!----></a></div></div><!--]--><!----><!----></nav></div><!--[--><!--]--></header><aside class="sidebar" data-v-83e92a68><nav class="nav-links nav" data-v-83e92a68 data-v-eab3edfe><!--[--><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/" data-v-b8818f8c>Home <!----></a></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>前端君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>面试八股文</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/algorithm" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>算法大卷</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/errormd/chrome插件开发指南" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>坑你太美</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>稀奇君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>web3</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/b" data-v-b8818f8c>杂谈君 <!----></a></div></div><!--]--><!----><!----></nav><!--[--><!--]--><ul class="sidebar-links" data-v-83e92a68><!--[--><li class="sidebar-link"><a class="sidebar-link-item" href="#第一种">第一种</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第二种-instanceof">第二种: instanceof</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#第三种判断方法：object-prototype-tostring">第三种判断方法：Object.prototype.toString</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#数据类型转换">数据类型转换</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#强制类型转换">强制类型转换</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#number-方法的强制转换规则">Number() 方法的强制转换规则</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#boolean-方法的强制转换规则">Boolean() 方法的强制转换规则</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#隐式类型转换">隐式类型转换</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#的隐式类型转换规则">&#39;==&#39; 的隐式类型转换规则</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#的隐式类型转换规则-1">&#39;+&#39; 的隐式类型转换规则</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#object-的转换规则">object 的转换规则</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#总结">总结</a><!----></li><!--]--></ul><!--[--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4><div class="container" data-v-7eddb2c4><!--[--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4><div><h1 id="数据类型的检测方法" tabindex="-1">数据类型的检测方法 <a class="header-anchor" href="#数据类型的检测方法" aria-hidden="true">#</a></h1><h2 id="第一种" tabindex="-1">第一种 <a class="header-anchor" href="#第一种" aria-hidden="true">#</a></h2><p>你可以看到，前 6 个都是基础数据类型，而为什么第 6 个 null 的 typeof 是 &#39;object&#39; 呢？这里要和你强调一下，虽然 typeof null 会输出 object，但这只是 JS 存在的一个悠久 Bug，不代表 null 就是引用数据类型，并且 null 本身也不是对象。因此，null 在 typeof 之后返回的是有问题的结果，不能作为判断 null 的方法。如果你需要在 if 语句中判断是否为 null，直接通过 ‘===null’来判断就好。</p><p>此外还要注意，引用数据类型 Object，用 typeof 来判断的话，除了 function 会判断为 OK 以外，其余都是 &#39;object&#39;，是无法判断出来的。</p><div class="language-"><pre><code>typeof 1 // &#39;number&#39;

typeof &#39;1&#39; // &#39;string&#39;

typeof undefined // &#39;undefined&#39;

typeof true // &#39;boolean&#39;

typeof Symbol() // &#39;symbol&#39;

typeof null // &#39;object&#39;

typeof [] // &#39;object&#39;

typeof {} // &#39;object&#39;

typeof console // &#39;object&#39;

typeof console.log // &#39;function&#39;

</code></pre></div><h2 id="第二种-instanceof" tabindex="-1">第二种: instanceof <a class="header-anchor" href="#第二种-instanceof" aria-hidden="true">#</a></h2><p>想必 instanceof 的方法你也听说过，我们 new 一个对象，那么这个新对象就是它原型链继承上面的对象了，通过 instanceof 我们能判断这个对象是否是之前那个构造函数生成的对象，这样就基本可以判断出这个新对象的数据类型。下面通过代码来了解一下。</p><div class="language-"><pre><code>let Car = function() {}

let benz = new Car()

benz instanceof Car // true

let car = new String(&#39;Mercedes Benz&#39;)

car instanceof String // true

let str = &#39;Covid-19&#39;

str instanceof String // false

</code></pre></div><p>上面就是用 instanceof 方法判断数据类型的大致流程，那么如果让你自己实现一个 instanceof 的底层实现，应该怎么写呢？请看下面的代码。</p><div class="language-javascript"><pre><code><span class="token keyword">function</span> <span class="token function">myInstanceof</span><span class="token punctuation">(</span><span class="token parameter">left<span class="token punctuation">,</span> right</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

  <span class="token comment">// 这里先用typeof来判断基础数据类型，如果是，直接返回false</span>

  <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> left <span class="token operator">!==</span> <span class="token string">&#39;object&#39;</span> <span class="token operator">||</span> left <span class="token operator">===</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

  <span class="token comment">// getProtypeOf是Object对象自带的API，能够拿到参数的原型对象</span>

  <span class="token keyword">let</span> proto <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>left<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>                  <span class="token comment">//循环往下寻找，直到找到相同的原型对象</span>

    <span class="token keyword">if</span><span class="token punctuation">(</span>proto <span class="token operator">===</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span><span class="token punctuation">(</span>proto <span class="token operator">===</span> right<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><span class="token comment">//找到相同原型对象，返回true</span>

    proto <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">getPrototypeof</span><span class="token punctuation">(</span>proto<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>

<span class="token comment">// 验证一下自己实现的myInstanceof是否OK</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">myInstanceof</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Number</span><span class="token punctuation">(</span><span class="token number">123</span><span class="token punctuation">)</span><span class="token punctuation">,</span> Number<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// true</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">myInstanceof</span><span class="token punctuation">(</span><span class="token number">123</span><span class="token punctuation">,</span> Number<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                <span class="token comment">// false</span>

</code></pre></div><p>现在你知道了两种判断数据类型的方法，那么它们之间有什么差异呢？我总结了下面两点：</p><ul><li><p>instanceof 可以准确地判断复杂引用数据类型，但是不能正确判断基础数据类型；</p></li><li><p>而 typeof 也存在弊端，它虽然可以判断基础数据类型（null 除外），但是引用数据类型中，除了 function 类型以外，其他的也无法判断。</p></li></ul><p>总之，不管单独用 typeof 还是 instanceof，都不能满足所有场景的需求，而只能通过二者混写的方式来判断。但是这种方式判断出来的其实也只是大多数情况，并且写起来也比较难受，你也可以试着写一下。</p><p>其实我个人还是比较推荐下面的第三种方法，相比上述两个而言，能更好地解决数据类型检测问题。</p><h3 id="第三种判断方法：object-prototype-tostring" tabindex="-1">第三种判断方法：Object.prototype.toString <a class="header-anchor" href="#第三种判断方法：object-prototype-tostring" aria-hidden="true">#</a></h3><p>toString() 是 Object 的原型方法，调用该方法，可以统一返回格式为 “[object Xxx]” 的字符串，其中 Xxx 就是对象的类型。对于 Object 对象，直接调用 toString() 就能返回 [object Object]；而对于其他对象，则需要通过 call 来调用，才能返回正确的类型信息。我们来看一下代码。</p><div class="language-Javascript"><pre><code><span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>       <span class="token comment">// &quot;[object Object]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>  <span class="token comment">// 同上结果，加上call也ok</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>    <span class="token comment">// &quot;[object Number]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token string">&#39;1&#39;</span><span class="token punctuation">)</span>  <span class="token comment">// &quot;[object String]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>  <span class="token comment">// &quot;[object Boolean]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>  <span class="token comment">// &quot;[object Function]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span>   <span class="token comment">//&quot;[object Null]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">)</span> <span class="token comment">//&quot;[object Undefined]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">123</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span>    <span class="token comment">//&quot;[object RegExp]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">//&quot;[object Date]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>       <span class="token comment">//&quot;[object Array]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span>  <span class="token comment">//&quot;[object HTMLDocument]&quot;</span>

<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>window<span class="token punctuation">)</span>   <span class="token comment">//&quot;[object Window]&quot;</span>

</code></pre></div><p>从上面这段代码可以看出，Object.prototype.toString.call() 可以很好地判断引用类型，甚至可以把 document 和 window 都区分开来。</p><p>但是在写判断条件的时候一定要注意，使用这个方法最后返回统一字符串格式为 &quot;[object Xxx]&quot; ，而这里字符串里面的 &quot;Xxx&quot; ，第一个首字母要大写（注意：使用 typeof 返回的是小写），这里需要多加留意。</p><p>那么下面来实现一个全局通用的数据类型判断方法，来加深你的理解，代码如下</p><div class="language-Javascript"><pre><code><span class="token keyword">function</span> <span class="token function">getType</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

  <span class="token keyword">let</span> type  <span class="token operator">=</span> <span class="token keyword">typeof</span> obj<span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">!==</span> <span class="token string">&quot;object&quot;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>    <span class="token comment">// 先进行typeof判断，如果是基础数据类型，直接返回</span>

    <span class="token keyword">return</span> type<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token comment">// 对于typeof返回结果是object的，再进行如下的判断，正则返回结果</span>

  <span class="token keyword">return</span> <span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\[object (\S+)\]$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">&#39;$1&#39;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 注意正则中间有个空格</span>

<span class="token punctuation">}</span>

<span class="token comment">/* 代码验证，需要注意大小写，哪些是typeof判断，哪些是toString判断？思考下 */</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>     <span class="token comment">// &quot;Array&quot; typeof []是object，因此toString返回</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token string">&#39;123&#39;</span><span class="token punctuation">)</span>  <span class="token comment">// &quot;string&quot; typeof 直接返回</span>

<span class="token function">getType</span><span class="token punctuation">(</span>window<span class="token punctuation">)</span> <span class="token comment">// &quot;Window&quot; toString返回</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span>   <span class="token comment">// &quot;Null&quot;首字母大写，typeof null是object，需toString来判断</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">)</span>   <span class="token comment">// &quot;undefined&quot; typeof 直接返回</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token punctuation">)</span>            <span class="token comment">// &quot;undefined&quot; typeof 直接返回</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// &quot;function&quot; typeof能判断，因此首字母小写</span>

<span class="token function">getType</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">123</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span>      <span class="token comment">//&quot;RegExp&quot; toString返回</span>

</code></pre></div><h2 id="数据类型转换" tabindex="-1">数据类型转换 <a class="header-anchor" href="#数据类型转换" aria-hidden="true">#</a></h2><p>在日常的业务开发中，经常会遇到 JavaScript 数据类型转换问题，有的时候需要我们主动进行强制转换，而有的时候 JavaScript 会进行隐式转换，隐式转换的时候就需要我们多加留心。</p><p>那么这部分都会涉及哪些内容呢？我们先看一段代码，了解下大致的情况。</p><div class="language-Javascript"><pre><code><span class="token string">&#39;123&#39;</span> <span class="token operator">==</span> <span class="token number">123</span>   <span class="token comment">// false or true?</span>

<span class="token string">&#39;&#39;</span> <span class="token operator">==</span> <span class="token keyword">null</span>    <span class="token comment">// false or true?</span>

<span class="token string">&#39;&#39;</span> <span class="token operator">==</span> <span class="token number">0</span>        <span class="token comment">// false or true?</span>

<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token number">0</span>        <span class="token comment">// false or true?</span>

<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">&#39;&#39;</span>       <span class="token comment">// false or true?</span>

<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token operator">!</span><span class="token punctuation">[</span><span class="token punctuation">]</span>      <span class="token comment">// false or true?</span>

<span class="token keyword">null</span> <span class="token operator">==</span> <span class="token keyword">undefined</span> <span class="token comment">//  false or true?</span>

<span class="token function">Number</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span>     <span class="token comment">// 返回什么？</span>

<span class="token function">Number</span><span class="token punctuation">(</span><span class="token string">&#39;&#39;</span><span class="token punctuation">)</span>      <span class="token comment">// 返回什么？</span>

<span class="token function">parseInt</span><span class="token punctuation">(</span><span class="token string">&#39;&#39;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// 返回什么？</span>

<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token operator">+</span><span class="token number">10</span>           <span class="token comment">// 返回什么？</span>

<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>

    <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>toPrimitive<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token keyword">return</span> <span class="token number">200</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span><span class="token punctuation">,</span>

    <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token keyword">return</span> <span class="token number">300</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span><span class="token punctuation">,</span>

    <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token keyword">return</span> <span class="token string">&#39;Hello&#39;</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj <span class="token operator">+</span> <span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 这里打印出来是多少？</span>

</code></pre></div><h3 id="强制类型转换" tabindex="-1">强制类型转换 <a class="header-anchor" href="#强制类型转换" aria-hidden="true">#</a></h3><p>强制类型转换方式包括 Number()、parseInt()、parseFloat()、toString()、String()、Boolean()，这几种方法都比较类似，通过字面意思可以很容易理解，都是通过自身的方法来进行数据类型的强制转换。下面我列举一些来详细说明。</p><p>上面代码中，第 8 行的结果是 0，第 9 行的结果同样是 0，第 10 行的结果是 NaN。这些都是很明显的强制类型转换，因为用到了 Number() 和 parseInt()。</p><p>其实上述几个强制类型转换的原理大致相同，下面我挑两个比较有代表性的方法进行讲解。</p><h3 id="number-方法的强制转换规则" tabindex="-1">Number() 方法的强制转换规则 <a class="header-anchor" href="#number-方法的强制转换规则" aria-hidden="true">#</a></h3><ul><li>如果是布尔值，true 和 false 分别转换为 1和0</li><li>如果是数字，返回自身；</li><li>如果是Null 返回0；</li><li>如果是undefined 返回nan</li><li>果是字符串，遵循以下规则：如果字符串中只包含数字（或者是 0X / 0x 开头的十六进制数字字符串，允许包含正负号），则将其转换为十进制；如果字符串中包含有效的浮点格式，将其转换为浮点数值；如果是空字符串，将其转换为 0；如果不是以上格式的字符串，均返回 NaN；</li><li>如果是 Symbol，抛出错误；</li><li>如果是对象，并且部署了 [Symbol.toPrimitive] ，那么调用此方法，否则调用对象的 valueOf() 方法，然后依据前面的规则转换返回的值；如果转换的结果是 NaN ，则调用对象的 toString() 方法，再次依照前面的顺序转换返回对应的值（Object 转换规则会在下面细讲）。</li></ul><p>下面通过一段代码来说明上述规则。</p><div class="language-"><pre><code>Number(true);        // 1

Number(false);       // 0

Number(&#39;0111&#39;);      //111

Number(null);        //0

Number(&#39;&#39;);          //0

Number(&#39;1a&#39;);        //NaN

Number(-0X11);       //-17

Number(&#39;0X11&#39;)       //17

</code></pre></div><h3 id="boolean-方法的强制转换规则" tabindex="-1">Boolean() 方法的强制转换规则 <a class="header-anchor" href="#boolean-方法的强制转换规则" aria-hidden="true">#</a></h3><p>这个方法的规则是：除了 undefined、 null、 false、 &#39;&#39;、 0（包括 +0，-0）、 NaN 转换出来是 false，其他都是 true。</p><p>这个规则应该很好理解，没有那么多条条框框，我们还是通过代码来形成认知，如下所示。</p><div class="language-"><pre><code>Boolean(0)          //false

Boolean(null)       //false

Boolean(undefined)  //false

Boolean(NaN)        //false

Boolean(1)          //true

Boolean(13)         //true

Boolean(&#39;12&#39;)       //true

</code></pre></div><p>其余的 parseInt()、parseFloat()、toString()、String() 这几个方法，你可以按照我的方式去整理一下规则，在这里不占过多篇幅了。</p><h3 id="隐式类型转换" tabindex="-1">隐式类型转换 <a class="header-anchor" href="#隐式类型转换" aria-hidden="true">#</a></h3><p>凡是通过逻辑运算符 (&amp;&amp;、 ||、 !)、运算符 (+、-、*、/)、关系操作符 (&gt;、 &lt;、 &lt;= 、&gt;=)、相等运算符 (==) 或者 if/while 条件的操作，如果遇到两个数据类型不一样的情况，都会出现隐式类型转换。这里你需要重点关注一下，因为比较隐蔽，特别容易让人忽视。</p><p>下面着重讲解一下日常用得比较多的“==”和“+”这两个符号的隐式转换规则。</p><h2 id="的隐式类型转换规则" tabindex="-1">&#39;==&#39; 的隐式类型转换规则 <a class="header-anchor" href="#的隐式类型转换规则" aria-hidden="true">#</a></h2><ul><li><p>如果类型相同，无须进行类型转换；</p></li><li><p>如果其中一个操作值是 null 或者 undefined，那么另一个操作符必须为 null 或者 undefined，才会返回 true，否则都返回 false；</p></li><li><p>如果其中一个是 Symbol 类型，那么返回 false；</p></li><li><p>两个操作值如果为 string 和 number 类型，那么就会将字符串转换为 number；</p></li><li><p>如果一个操作值是 boolean，那么转换成 number；</p></li><li><p>如果一个操作值为 object 且另一方为 string、number 或者 symbol，就会把 object 转为原始类型再进行判断（调用 object 的 valueOf/toString 方法进行转换）。</p></li></ul><div class="language-javascript"><pre><code><span class="token keyword">null</span> <span class="token operator">==</span> <span class="token keyword">undefined</span>       <span class="token comment">// true  规则2</span>

<span class="token keyword">null</span> <span class="token operator">==</span> <span class="token number">0</span>               <span class="token comment">// false 规则2</span>

<span class="token string">&#39;&#39;</span> <span class="token operator">==</span> <span class="token keyword">null</span>              <span class="token comment">// false 规则2</span>

<span class="token string">&#39;&#39;</span> <span class="token operator">==</span> <span class="token number">0</span>                 <span class="token comment">// true  规则4 字符串转隐式转换成Number之后再对比</span>

<span class="token string">&#39;123&#39;</span> <span class="token operator">==</span> <span class="token number">123</span>            <span class="token comment">// true  规则4 字符串转隐式转换成Number之后再对比</span>

<span class="token number">0</span> <span class="token operator">==</span> <span class="token boolean">false</span>              <span class="token comment">// true  e规则 布尔型隐式转换成Number之后再对比</span>

<span class="token number">1</span> <span class="token operator">==</span> <span class="token boolean">true</span>               <span class="token comment">// true  e规则 布尔型隐式转换成Number之后再对比</span>

<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token punctuation">{</span>

  value<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>

  <span class="token function-variable function">valueOf</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token operator">++</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// 注意这里a又可以等于1、2、3</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a <span class="token operator">==</span> <span class="token number">1</span> <span class="token operator">&amp;&amp;</span> a <span class="token operator">==</span> <span class="token number">2</span> <span class="token operator">&amp;&amp;</span> a <span class="token operator">==</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">//true f规则 Object隐式转换</span>

<span class="token comment">// 注：但是执行过3遍之后，再重新执行a==3或之前的数字就是false，因为value已经加上去了，这里需要注意一下</span>

</code></pre></div><h2 id="的隐式类型转换规则-1" tabindex="-1">&#39;+&#39; 的隐式类型转换规则 <a class="header-anchor" href="#的隐式类型转换规则-1" aria-hidden="true">#</a></h2><p>&#39;+&#39; 号操作符，不仅可以用作数字相加，还可以用作字符串拼接。仅当 &#39;+&#39; 号两边都是数字时，进行的是加法运算；如果两边都是字符串，则直接拼接，无须进行隐式类型转换。</p><p>除了上述比较常规的情况外，还有一些特殊的规则，如下所示。</p><ul><li><p>如果其中有一个是字符串，另外一个是 undefined、null 或布尔型，则调用 toString() 方法进行字符串拼接；如果是纯对象、数组、正则等，则默认调用对象的转换方法会存在优先级（下一讲会专门介绍），然后再进行拼接。</p></li><li><p>如果其中有一个是数字，另外一个是 undefined、null、布尔型或数字，则会将其转换成数字进行加法运算，对象的情况还是参考上一条规则。</p></li><li><p>如果其中一个是字符串、一个是数字，则按照字符串规则进行拼接。</p></li></ul><p>下面还是结合代码来理解上述规则，如下所示。</p><div class="language-"><pre><code>1 + 2        // 3  常规情况

&#39;1&#39; + &#39;2&#39;    // &#39;12&#39; 常规情况

// 下面看一下特殊情况

&#39;1&#39; + undefined   // &quot;1undefined&quot; 规则1，undefined转换字符串

&#39;1&#39; + null        // &quot;1null&quot; 规则1，null转换字符串

&#39;1&#39; + true        // &quot;1true&quot; 规则1，true转换字符串

&#39;1&#39; + 1n          // &#39;11&#39; 比较特殊字符串和BigInt相加，BigInt转换为字符串

1 + undefined     // NaN  规则2，undefined转换数字相加NaN

1 + null          // 1    规则2，null转换为0

1 + true          // 2    规则2，true转换为1，二者相加为2

1 + 1n            // 错误  不能把BigInt和Number类型直接混合相加

&#39;1&#39; + 3           // &#39;13&#39; 规则3，字符串拼接

</code></pre></div><h2 id="object-的转换规则" tabindex="-1">object 的转换规则 <a class="header-anchor" href="#object-的转换规则" aria-hidden="true">#</a></h2><p>对象转换的规则，会先调用内置的 [ToPrimitive] 函数，其规则逻辑如下：</p><p>如果部署了 Symbol.toPrimitive 方法，优先调用再返回；</p><p>调用 valueOf()，如果转换为基础类型，则返回；</p><p>调用 toString()，如果转换为基础类型，则返回；</p><p>如果都没有返回基础类型，会报错。</p><p>直接理解有些晦涩，还是直接来看代码，你也可以在控制台自己敲一遍来加深印象。</p><div class="language-Javascript"><pre><code><span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>

  value<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>

  <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token number">2</span><span class="token punctuation">;</span>

  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token string">&#39;3&#39;</span>

  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>toPrimitive<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token number">4</span>

  <span class="token punctuation">}</span>

<span class="token punctuation">}</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 输出5</span>

<span class="token comment">// 因为有Symbol.toPrimitive，就优先执行这个；如果Symbol.toPrimitive这段代码删掉，则执行valueOf打印结果为3；如果valueOf也去掉，则调用toString返回&#39;31&#39;(字符串拼接)</span>

<span class="token comment">// 再看两个特殊的case：</span>

<span class="token number">10</span> <span class="token operator">+</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token comment">// &quot;10[object Object]&quot;，注意：{}会默认调用valueOf是{}，不是基础类型继续转换，调用toString，返回结果&quot;[object Object]&quot;，于是和10进行&#39;+&#39;运算，按照字符串拼接规则来，参考&#39;+&#39;的规则C</span>

<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token keyword">undefined</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token number">10</span>

<span class="token comment">// &quot;1,2,,4,510&quot;，注意[1,2,undefined,4,5]会默认先调用valueOf结果还是这个数组，不是基础数据类型继续转换，也还是调用toString，返回&quot;1,2,,4,5&quot;，然后再和10进行运算，还是按照字符串拼接规则，参考&#39;+&#39;的第3条规则</span>

</code></pre></div><h2 id="总结" tabindex="-1">总结 <a class="header-anchor" href="#总结" aria-hidden="true">#</a></h2><ul><li><p>数据类型的基本概念：这是必须掌握的知识点，作为深入理解 JavaScript 的基础。</p></li><li><p>数据类型的判断方法：typeof 和 instanceof，以及 Object.prototype.toString 的判断数据类型、手写 instanceof 代码片段，这些是日常开发中经常会遇到的，因此你需要好好掌握。</p></li><li><p>数据类型的转换方式：两种数据类型的转换方式，日常写代码过程中隐式转换需要多留意，如果理解不到位，很容易引起在编码过程中的 bug，得到一些意想不到的结果。</p></li></ul></div></div><footer class="page-footer" data-v-7eddb2c4 data-v-fb8d84c6><div class="edit" data-v-fb8d84c6><div class="edit-link" data-v-fb8d84c6 data-v-1ed99556><!----></div></div><div class="updated" data-v-fb8d84c6><!----></div></footer><!----><!--[--><!--]--></div></main></div><!----><!--]--></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"fe_algorithm.md\":\"e1054222\",\"fe_errormd_chrome插件开发指南.md\":\"8310a77a\",\"fe_errormd_mysql密码遗忘.md\":\"37b8860e\",\"fe_secondary_javascript_descriptors.md\":\"cd9a7474\",\"fe_secondary_javascript_javascript.md\":\"42853649\",\"fe_secondary_javascript_jicheng.md\":\"1cd0c4dc\",\"fe_secondary_javascript_jscopy.md\":\"66795111\",\"fe_secondary_javascript_js数据类型.md\":\"c6bc851f\",\"fe_secondary_javascript_let const var 的区别.md\":\"685e3545\",\"fe_secondary_javascript_weakmap.md\":\"2a0ba820\",\"fe_secondary_javascript_作用域.md\":\"220cfcf9\",\"fe_secondary_javascript_变量提升.md\":\"b63f20ee\",\"fe_secondary_javascript_闭包.md\":\"5404cbcf\",\"fe_secondary_python_基础知识.md\":\"ae39dc27\",\"fe_secondary_vite_vite杂烩记录.md\":\"aa7cf9a4\",\"fe_secondary_webpack_loader与plugin的不同.md\":\"e2712a7c\",\"fe_secondary_interviews_jstype.md\":\"b3e700ba\",\"fe_secondary_interviews_mianshi.md\":\"218f21c3\",\"fe_secondary_interviews_modular.md\":\"38434f4f\",\"fe_secondary_interviews_network.md\":\"d5842ea6\",\"fe_suanfa_tree树结构.md\":\"d41c852f\",\"fe_suanfa_二分查找.md\":\"28f745d1\",\"fe_suanfa_二叉树.md\":\"836f7969\",\"fe_suanfa_二叉树后序遍历.md\":\"af43c381\",\"fe_suanfa_二叉树展开链表.md\":\"cc410293\",\"fe_suanfa_二叉树最小深度.md\":\"d272316f\",\"fe_suanfa_二叉树的所有路径.md\":\"70f2feac\",\"fe_suanfa_二叉树的最大深度.md\":\"ab1fe25c\",\"fe_suanfa_冒泡排序.md\":\"b91ecca4\",\"fe_suanfa_前中后序遍历.md\":\"997426ab\",\"fe_suanfa_前缀和.md\":\"6ec90ae8\",\"fe_suanfa_区域和检索数组不可变.md\":\"6e447cdb\",\"fe_suanfa_反转数组.md\":\"c28c7d5f\",\"fe_suanfa_将有序数组转换为二叉搜索树.md\":\"6a79c21d\",\"fe_suanfa_差分.md\":\"101d6b54\",\"fe_suanfa_快速排序.md\":\"575fe1af\",\"fe_suanfa_插入排序.md\":\"078511c5\",\"fe_suanfa_滑动窗口.md\":\"08f684ff\",\"fe_suanfa_翻转二叉树.md\":\"1a866015\",\"fe_suanfa_选择排序.md\":\"a25eac11\",\"fe_suanfa_链表反转.md\":\"a642cc7a\",\"fe_web3_ethers_01-hellovitalik.md\":\"162c31f8\",\"fe_web3_ethers_02-合约交互.md\":\"08f30902\",\"fe_web3_ethers_03-发送eth.md\":\"fbf8825d\",\"index.md\":\"64947f2b\"}")</script>
    <script type="module" async src="/blobview/assets/app.a4363fd4.js"></script>
    
  </body>
</html>